home *** CD-ROM | disk | FTP | other *** search
Wrap
CCCCoooommmmmmmmaaaannnndddd WWWWrrrriiiittttiiiinnnngggg((((3333TTTTccccllll)))) CCCCoooommmmmmmmaaaannnndddd WWWWrrrriiiittttiiiinnnngggg((((3333TTTTccccllll)))) NNNNAAAAMMMMEEEE TclCommandWriting - Writing C language extensions to Tcl. OOOOVVVVEEEERRRRVVVVIIIIEEEEWWWW This document is intended to help the programmer who wishes to extend Tcl with C language routines. It should also be useful to someone wishing to add Tcl to an existing editor, communications program, window manager, etc. C programming information can also be found in the *._3 manual pages in the _d_o_c directory of the Berkeley distribution, and in the *._3 manpages in the _m_a_n directory of Extended Tcl. WWWWRRRRIIIITTTTIIIINNNNGGGG TTTTCCCCLLLL EEEEXXXXTTTTEEEENNNNSSSSIIIIOOOONNNNSSSS IIIINNNN CCCC All C-based Tcl commands are called with four arguments: a client data pointer, an interpreter pointer, an argument count and a pointer to an array of pointers to character strings containing the Tcl arguments to the command. A simple Tcl extension in C is now presented, and described below: #include "tcl.h" int App_EchoCmd(clientData, interp, argc, argv) void *clientData; Tcl_Interp *interp; int argc; char **argv; { int i; for (i = 1; i < argc; i++) { printf("%s",argv[i]); if (i < argc - 1) printf(" "); } printf("\n"); return TCL_OK; } The client data pointer will be described later. The interpreter pointer is the ``key'' to an interpreter. It is returned by TTTTccccllll____CCCCrrrreeeeaaaatttteeeeIIIInnnntttteeeerrrrpppp and is used extensively within Tcl, and will be by your C extensions. The data structure pointed to by the interpreter pointer, and all of the subordinate structures that branch off of it, make up a Tcl interpreter, which includes all of the currently defined procedures, commands, variables, arrays and the execution state of that interpreter. (For more information on creating and deleting interpreters, please examine the CCCCrrrrttttIIIInnnntttteeeerrrrpppp(3) manpage in the Berkeley Tcl distribution. For information on creating interpreters that include the commands provided by Extended Tcl, check out the TTTTccccllllXXXX____IIIInnnniiiitttt(3) manpage of Extended Tcl. For a manual page describing the user-visible fields of a Tcl interpreter, please look at IIIInnnntttteeeerrrrpppp(3) in Berkeley Tcl.) PPPPaaaaggggeeee 1111 CCCCoooommmmmmmmaaaannnndddd WWWWrrrriiiittttiiiinnnngggg((((3333TTTTccccllll)))) CCCCoooommmmmmmmaaaannnndddd WWWWrrrriiiittttiiiinnnngggg((((3333TTTTccccllll)))) The argument count and pointer to an array of pointers to textual arguments is handled by your C code in the same manner that you would use in writing a C _m_a_i_n function -- the argument count and array of pointers works the same as in a C _m_a_i_n call; pointers to the arguments to the function are contained in the _a_r_g_v array. Similar to a C main, the first argument (_a_r_g_v[_0]) is the name the routine was called as (in a main, the name the program was invoked as). In the above example, all of the arguments are output with a space between each one by looping through _a_r_g_v from one to the argument count, _a_r_g_c, and a newline is output to terminate the line -- an ``echo'' command. All arguments from a Tcl call to a Tcl C extension are passed as strings. If your C routine expects certain numeric arguments, your routine must first convert them using the TTTTccccllll____GGGGeeeettttIIIInnnntttt or TTTTccccllll____GGGGeeeettttDDDDoooouuuubbbblllleeee function, Extended Tcl's TTTTccccllll____GGGGeeeettttLLLLoooonnnngggg or TTTTccccllll____GGGGeeeettttUUUUnnnnssssiiiiggggnnnneeeedddd, or some other method of your own devising. Likewise for converting boolean values, TTTTccccllll____GGGGeeeettttBBBBoooooooolllleeeeaaaannnn should be used. These routines automatically leave an appropriate error message in the Tcl interpreter's result buffer and return TTTTCCCCLLLL____EEEERRRRRRRROOOORRRR if a conversion error occurs. (For more information on these routines, please look at the GGGGeeeettttIIIInnnntttt(3) manpage in the Berkeley Tcl distribution.) Likewise, if you program produces a numeric result, it should return a string equivalent to that numeric value. A common way of doing this is something like... sprintf(interp->result, "%ld", result); Writing results directly into the interpreter's result buffer is only good for relatively short results. Tcl has a function, TTTTccccllll____SSSSeeeettttRRRReeeessssuuuulllltttt, which provides the ability for your C extensions to return very large strings to Tcl, with the ability to tell the interpreter whether it ``owns'' the string (meaning that Tcl should delete the string when it's done with it), that the string is likely to be changed or overwritten soon (meaning that Tcl should make a copy of the string right away), or that the string won't change (so Tcl can use the string as is and not worry about it). Understanding how results are passed back to Tcl is essential to the C extension writer. Please study the SSSSeeeettttRRRReeeessssuuuulllltttt(3) manual page in the Tcl distribution. Sophisticated commands should verify their arguments whenever possible, both by examining the argument count, by verifying that numeric fields are really numeric, that values are in range (when their ranges are known), and so forth. Tcl is designed to be as bullet-proof as possible, in the sense that no Tcl program should be able to cause Tcl to dump core. Please carry this notion forward with your C extensions by validating arguments as above. PPPPaaaaggggeeee 2222 CCCCoooommmmmmmmaaaannnndddd WWWWrrrriiiittttiiiinnnngggg((((3333TTTTccccllll)))) CCCCoooommmmmmmmaaaannnndddd WWWWrrrriiiittttiiiinnnngggg((((3333TTTTccccllll)))) AAAANNNNOOOOTTTTHHHHEEEERRRR CCCC EEEEXXXXTTTTEEEENNNNSSSSIIIIOOOONNNN ---- TTTTHHHHEEEE MMMMAAAAXXXX In the command below, two or more arguments are compared and the one with the maximum value is returned, if all goes well. It is an error if there are fewer than three arguments (the pointer to the ``max'' command text itself, _a_r_g_v[_0], and pointers to at least two arguments to compare the values of). This routine also shows the use of the programmer labor-saving TTTTccccllll____AAAAppppppppeeeennnnddddRRRReeeessssuuuulllltttt routine. See the Tcl manual page, SSSSeeeettttRRRReeeessssuuuulllltttt(3), for details. Also examine the calls TTTTccccllll____AAAAddddddddEEEErrrrrrrroooorrrrIIIInnnnffffoooo, TTTTccccllll____SSSSeeeettttEEEErrrrrrrroooorrrrCCCCooooddddeeee and TTTTccccllll____PPPPoooossssiiiixxxxEEEErrrrrrrroooorrrr documented in the Tcl manual page AAAAddddddddEEEErrrrrrrrIIIInnnnffffoooo(3). int Tcl_MaxCmd (clientData, interp, argc, argv) char *clientData; Tcl_Interp *interp; int argc; char **argv; { int maxVal = MININT; int maxIdx = 1; int value, idx; if (argc < 3) { Tcl_AppendResult (interp, "bad # arg: ", argv[0], " num1 num2 [..numN]", (char *)NULL); return TCL_ERROR; } for (idx = 1; idx < argc; idx++) { if (Tcl_GetInt (argv[idx], 10, &Value) != TCL_OK) return TCL_ERROR; if (value > maxVal) { maxVal = value; maxIdx = idx; } } Tcl_SetResult (interp, argv [maxIdx], TCL_VOLATILE); return TCL_OK; } When Tcl-callable functions complete, they should normally return TTTTCCCCLLLL____OOOOKKKK or TTTTCCCCLLLL____EEEERRRRRRRROOOORRRR. TTTTCCCCLLLL____OOOOKKKK is returned when the command succeeded and TTTTCCCCLLLL____EEEERRRRRRRROOOORRRR is returned when the command has failed in some abnormal way. TTTTCCCCLLLL____EEEERRRRRRRROOOORRRR should be returned for all syntax errors, non-numeric values (when numeric ones were expected), and so forth. Less clear in some cases is whether Tcl errors should be returned or whether a function should just return a status value. For example, end-of-file during a _g_e_t_s returns a status, but _o_p_e_n returns an error if the open fails. Errors can be caught from Tcl programs using the _c_a_t_c_h command. (See PPPPaaaaggggeeee 3333 CCCCoooommmmmmmmaaaannnndddd WWWWrrrriiiittttiiiinnnngggg((((3333TTTTccccllll)))) CCCCoooommmmmmmmaaaannnndddd WWWWrrrriiiittttiiiinnnngggg((((3333TTTTccccllll)))) Tcl's ccccaaaattttcccchhhh(n) and eeeerrrrrrrroooorrrr(n) manual pages.) Less common return values are TTTTCCCCLLLL____RRRREEEETTTTUUUURRRRNNNN, TTTTCCCCLLLL____BBBBRRRREEEEAAAAKKKK and TTTTCCCCLLLL____CCCCOOOONNNNTTTTIIIINNNNUUUUEEEE. These are used if you are adding new control and/or looping structures to Tcl. To see these values in action, examine the source code to Tcl's _w_h_i_l_e, _f_o_r and _i_f, and Extended Tcl's _l_o_o_p commands. Note the call to _T_c_l__S_e_t_R_e_s_u_l_t in the above command to set the return value to Tcl. TTTTCCCCLLLL____VVVVOOOOLLLLAAAATTTTIIIILLLLEEEE is used because the memory containing the result will be freed upon the function's return. AAAANNNNOOOOTTTTHHHHEEEERRRR CCCC EEEEXXXXTTTTEEEENNNNSSSSIIIIOOOONNNN ---- TTTTHHHHEEEE LLLLRRRREEEEVVVVEEEERRRRSSSSEEEE In the command below, one list is passed as an argument, and a list containing all of the elements of the list in reverse order is returned. It is an error if anything other than two arguments are passed (the pointer to the ``lreverse'' command text itself, _a_r_g_v[_0], and a pointer to the list to reverse. Once _l_r_e_v_e_r_s_e has determined that it has received the correct number of arguments, TTTTccccllll____SSSSpppplllliiiittttLLLLiiiisssstttt is called to break the list into an _a_r_g_c and _a_r_g_v array of pointers. _l_r_e_v_e_r_s_e then operates on the array of pointers, swapping them from lowest to highest, second-lowest to second-highest, and so forth. Finally TTTTccccllll____MMMMeeeerrrrggggeeee is calleds to create a single new string containing the reversed list and it is set as the result via TTTTccccllll____SSSSeeeettttRRRReeeessssuuuulllltttt. Note that TTTTCCCCLLLL____DDDDYYYYNNNNAAAAMMMMIIIICCCC is used to tell TTTTccccllll____SSSSeeeettttRRRReeeessssuuuulllltttt that it now owns the string and it is up to Tcl to free the string when it is done with it. Note that it _i_s safe to play around with the _a_r_g_v list like this, and that a single call to cccckkkkffffrrrreeeeeeee can be made to free all the data returned by TTTTccccllll____SSSSpppplllliiiittttLLLLiiiisssstttt in this manner. int Tcl_LreverseCmd(notUsed, interp, argc, argv) ClientData notUsed; /* Not used. */ Tcl_Interp *interp; /* Current interpreter. */ int argc; /* Number of arguments. */ char **argv; /* Argument strings. */ { int listArgc, lowListIndex, hiListIndex; char **listArgv; char *temp, *resultList; if (argc != 2) { Tcl_AppendResult(interp, "wrong # args: should be " list return TCL_ERROR; } PPPPaaaaggggeeee 4444 CCCCoooommmmmmmmaaaannnndddd WWWWrrrriiiittttiiiinnnngggg((((3333TTTTccccllll)))) CCCCoooommmmmmmmaaaannnndddd WWWWrrrriiiittttiiiinnnngggg((((3333TTTTccccllll)))) if (Tcl_SplitList(interp, argv[1], &listArgc, &listArgv) != TCL_OK) { return TCL_ERROR; } for (lowListIndex = 0, hiListIndex = listArgc; --hiListIndex > lowListIndex; lowListIndex++) { temp = listArgv[lowListIndex]; listArgv[lowListIndex] = listArgv[hiListIndex]; listArgv[hiListIndex] = temp; } resultList = Tcl_Merge (listArgc, listArgv); ckfree (listArgv); Tcl_SetResult (interp, resultList, TCL_DYNAMIC); return TCL_OK; } IIIINNNNSSSSTTTTAAAALLLLLLLLIIIINNNNGGGG YYYYOOOOUUUURRRR CCCCOOOOMMMMMMMMAAAANNNNDDDD To install your command into Tcl you must call TTTTccccllll____CCCCrrrreeeeaaaatttteeeeCCCCoooommmmmmmmaaaannnndddd, passing it the pointer to the interpreter you want to install the command into, the name of the command, a pointer to the C function that implements the command, a client data pointer, and a pointer to an optional callback routine. The client data pointer and the callback routine will be described later. For example, for the max function above (which, incidentally, comes from TclX's tclXmath.c in the _T_c_l_X_7._4/_s_r_c directory): Tcl_CreateCommand (interp, "max", Tcl_MaxCmd, (ClientData)NULL, (void (*)())NULL); In the above example, the max function is added to the specified interpreter. The client data pointer and callback function pointer are NULL. (For complete information on TTTTccccllll____CCCCrrrreeeeaaaatttteeeeCCCCoooommmmmmmmaaaannnndddd and its companion routine, TTTTccccllll____CCCCoooommmmmmmmaaaannnnddddIIIInnnnffffoooo, please examine the CCCCrrrrttttCCCCoooommmmmmmmaaaannnndddd(3) command page in the Berkeley Tcl distribution.) DDDDYYYYNNNNAAAAMMMMIIIICCCC SSSSTTTTRRRRIIIINNNNGGGGSSSS _D_y_n_a_m_i_c _s_t_r_i_n_g_s are an important abstraction that first became available with Tcl 7.0. Dynamic strings, or _D_S_t_r_i_n_g_s, provide a way to build up arbitrarily long strings through a repeated process of appending information to them. DStrings reduce the amount of allocating and copying required to add information to a string. Further, they simplify the process of doing so. For complete information on dynamic strings, please examine the DDDDSSSSttttrrrriiiinnnngggg(3) manual page in the Berkeley Tcl distribution. CCCCLLLLIIIIEEEENNNNTTTT DDDDAAAATTTTAAAA The client data pointer provides a means for Tcl commands to have data associated with them that is not global to the C program nor included in the Tcl core. Client data is essential in a multi-interpreter environment (where a single program has created and is making use of multiple Tcl interpreters) for the C routines to maintain any permanent PPPPaaaaggggeeee 5555 CCCCoooommmmmmmmaaaannnndddd WWWWrrrriiiittttiiiinnnngggg((((3333TTTTccccllll)))) CCCCoooommmmmmmmaaaannnndddd WWWWrrrriiiittttiiiinnnngggg((((3333TTTTccccllll)))) data they need on a per-interpreter basis. Otherwise there would be reentrancy problems. Tcl solves this through the client data mechanism. When you are about to call TTTTccccllll____CCCCrrrreeeeaaaatttteeeeCCCCoooommmmmmmmaaaannnndddd to add a new command to an interpreter, if that command needs to keep some read/write data across invocations, you should allocate the space, preferably using cccckkkkaaaalllllllloooocccc, then pass the address of that space as the ClientData pointer to TTTTccccllll____CCCCrrrreeeeaaaatttteeeeCCCCoooommmmmmmmaaaannnndddd. When your command is called from Tcl, the ClientData pointer you gave to TTTTccccllll____CCCCrrrreeeeaaaatttteeeeCCCCoooommmmmmmmaaaannnndddd when you added the command to that interpreter is passed to your C routine through the ClientData pointer calling argument. Commands that need to share this data with one another can do so by using the same ClientData pointer when the commands are added. It is important to note that the Tcl extensions in the _t_c_l_X_7._4/_s_r_c directory have had all of their data set up in this way. Since release 6.2, Extended Tcl has supported multiple interpreters within one invocation of Tcl. TTTTHHHHEEEEOOOORRRRYYYY OOOOFFFF HHHHAAAANNNNDDDDLLLLEEEESSSS Sometimes you need to have a data element that isn't readily representable as a string within Tcl, for example a pointer to a complex C data structure. It is not a good idea to try to pass pointers around within Tcl as strings by converting them to and from hex or integer representations, for example. It is too easy to mess one up, and the likely outcome of doing that is a core dump. Instead we have developed and made use of the concept of _h_a_n_d_l_e_s. Handles are identifiers a C extension can pass to, and accept from, Tcl to make the transition between what your C code knows something as and what name Tcl knows it by to be as safe and painless as possible. For example, the stdio package included in Tcl uses file handles. When you open a file from Tcl, a handle is returned of the form ffffiiiilllleeee_n where _n is a file number. When you pass the file handle back to _p_u_t_s, _g_e_t_s, _s_e_e_k, _f_l_u_s_h and so forth, they validate the file handle by checking the the ffffiiiilllleeee text is present, then converting the file number to an integer that they use to look into a data structure of pointers to Tcl open file structures, which contain a Unix file descriptor, flags indicating whether or not the file is currently open, whether the file is a file or a pipe and so forth. Handles have proven so useful that, as of release 6.1a, general support has been added for them. If you need a similar capability, it would be best to use the handle routines, documented in HHHHaaaannnnddddlllleeeessss(3) in Extended Tcl. We recommend that you use a unique-to-your-package textual handle coupled with a specific identifier and let the handle management routines validate it when it's passed back. It is much easier to track down a bug with an implicated handle named something like ffffiiiilllleeee4444 or bbbbiiiittttmmmmaaaapppp6666 than just 6666. PPPPaaaaggggeeee 6666 CCCCoooommmmmmmmaaaannnndddd WWWWrrrriiiittttiiiinnnngggg((((3333TTTTccccllll)))) CCCCoooommmmmmmmaaaannnndddd WWWWrrrriiiittttiiiinnnngggg((((3333TTTTccccllll)))) TTTTRRRRAAAACCCCKKKKIIIINNNNGGGG MMMMEEEEMMMMOOOORRRRYYYY CCCCOOOORRRRRRRRUUUUPPPPTTTTIIIIOOOONNNN PPPPRRRROOOOBBBBLLLLEEEEMMMMSSSS Occasionally you may write code that scribbles past the end of an allocated piece of memory. The memory debugging routines included in Tcl can help find these problems. See _M_e_m_o_r_y(_T_C_L) for details. IIIINNNNSSSSTTTTAAAALLLLLLLLIIIINNNNGGGG YYYYOOOOUUUURRRR EEEEXXXXTTTTEEEENNNNSSSSIIIIOOOONNNNSSSS IIIINNNNTTTTOOOO EEEEXXXXTTTTEEEENNNNDDDDEEEEDDDD TTTTCCCCLLLL To add your extensions to Extended Tcl, you must compile them and cause them to be linked with TclX. For the routines to be linked into the ttttccccllll and wwwwiiiisssshhhhxxxx executables, they must be referenced (directly or indirectly) from TclX. For these extensions to be visible as Tcl commands, they must be installed into Tcl with TTTTccccllll____CCCCrrrreeeeaaaatttteeeeCCCCoooommmmmmmmaaaannnndddd. Application-specific startup is accomplished by creating or editing the _T_c_l__A_p_p_I_n_i_t function. In _T_c_l__A_p_p_I_n_i_t you should add a call to an application-specific init function which you create. This function should take the address of the interpreter it should install its commands into, and it should install those commands with TTTTccccllll____CCCCrrrreeeeaaaatttteeeeCCCCoooommmmmmmmaaaannnndddd and do any other application-specific startup that is necessary. The naming convention for application startup routines is AAAApppppppp____IIIInnnniiiitttt, where _A_p_p is the name of your application. For example, to add an application named _c_u_t_e one would create a _C_u_t_e__I_n_i_t routine that expected a TTTTccccllll____IIIInnnntttteeeerrrrpppp pointer as an argument, and add the following code to _T_c_l__A_p_p_I_n_i_t: if (Cute_Init (interp) == TCL_ERROR) { return TCL_ERROR; } As you can guess from the above example, if your init routine is unable to initialize, it should use TTTTccccllll____AAAAppppppppeeeennnnddddRRRReeeessssuuuulllltttt to provide some kind of useful error message back to TclX, then return TTTTCCCCLLLL____EEEERRRRRRRROOOORRRR to indicate that an error occurred. If the routine executed successfully, it should return TTTTCCCCLLLL____OOOOKKKK. When you examine _T_c_l__A_p_p_I_n_i_t, note that there is one call already there to install an application -- the call to _T_c_l_X__I_n_i_t installs Extended Tcl into the Tcl core. MMMMAAAAKKKKIIIINNNNGGGG AAAAPPPPPPPPLLLLIIIICCCCAAAATTTTIIIIOOOONNNN IIIINNNNFFFFOOOORRRRMMMMAAAATTTTIIIIOOOONNNN VVVVIIIISSSSIIIIBBBBLLLLEEEE FFFFRRRROOOOMMMM EEEEXXXXTTTTEEEENNNNDDDDEEEEDDDD TclX's iiiinnnnffffooooxxxx command can return several pieces of information relevant to Extended Tcl, including the application's name, descriptive name, patch level and version. Your application's startup can set these variables to application-specific values. If it doesn't, they are given default values for Extended Tcl. To set these values, first be sure that you include either ttttccccllllEEEExxxxtttteeeennnndddd....hhhh or ttttccccllllEEEExxxxttttddddIIIInnnntttt....hhhh from the source file that defines your init routine. This will create external declarations for the variables. Then, set the variables in your init route, for example: PPPPaaaaggggeeee 7777 CCCCoooommmmmmmmaaaannnndddd WWWWrrrriiiittttiiiinnnngggg((((3333TTTTccccllll)))) CCCCoooommmmmmmmaaaannnndddd WWWWrrrriiiittttiiiinnnngggg((((3333TTTTccccllll)))) tclAppName = "cute"; tclAppLongName = "Call Unix/Tcl Environment"; tclAppVersion = "2.1"; Note that the default values are set by _T_c_l_X__I_n_i_t, so if you wish to override them, you must call your init routine in _T_c_l__A_p_p_I_n_i_t after its call to _T_c_l_X__I_n_i_t. EEEEXXXXTTTTEEEENNNNDDDDEEEEDDDD TTTTCCCCLLLL EEEEXXXXIIIITTTT When Extended Tcl exits, TTTTccccllll____DDDDeeeelllleeeetttteeeeIIIInnnntttteeeerrrrpppp may be called to free memory used by Tcl -- normally, this is only called if TTTTCCCCLLLL____MMMMEEEEMMMM____DDDDEEEEBBBBUUUUGGGG was defined, since Unix will return all of the allocated memory back to the system, anyway. If TTTTCCCCLLLL____MMMMEEEEMMMM____DDDDEEEEBBBBUUUUGGGG was defined, it is called so that any memory that was allocated without ever being freed can be detected. This greatly reduces the amount of work to detect and track down memory leaks, a situation where some piece of your code allocates memory repeatedly without ever freeing it, or without always freeing it. It is often necessary for an application to perform special cleanup functions upon the deletion of an interpreter as well. To facilitate this activity, Tcl provides the ability to perform a function callback when an interpreter is deleted. To arrange for a C function to be called when the interpreter is deleted, call TTTTccccllll____CCCCaaaallllllllWWWWhhhheeeennnnDDDDeeeelllleeeetttteeeedddd from your application initialization routine. For details on how to use this function, read the CCCCaaaallllllllDDDDeeeellll(3) manual page that ships with Berkeley Tcl. EEEEXXXXEEEECCCCUUUUTTTTIIIINNNNGGGG TTTTCCCCLLLL CCCCOOOODDDDEEEE FFFFRRRROOOOMMMM YYYYOOOOUUUURRRR CCCC Suppose you are in the middle of coding a C extension and you realize that you need some operation performed, one that would be simple from Tcl but possibly excruciating to do directly in C. Tcl provides the TTTTccccllll____EEEEvvvvaaaallll, TTTTccccllll____VVVVaaaarrrrEEEEvvvvaaaallll, TTTTccccllll____EEEEvvvvaaaallllFFFFiiiilllleeee and TTTTccccllll____GGGGlllloooobbbbaaaallllEEEEvvvvaaaallll functions for the purpose of executing Tcl code from within a C extension. The results of the call will be in iiiinnnntttteeeerrrrpppp---->>>>rrrreeeessssuuuulllltttt. For more information please consult the EEEEvvvvaaaallll(3) manual page within the Berkely Tcl distribution. AAAACCCCCCCCEEEESSSSSSSSIIIINNNNGGGG TTTTCCCCLLLL VVVVAAAARRRRIIIIAAAABBBBLLLLEEEESSSS AAAANNNNDDDD AAAARRRRRRRRAAAAYYYYSSSS FFFFRRRROOOOMMMM Tcl variables and arrays can be read from a C extension through the TTTTccccllll____GGGGeeeettttVVVVaaaarrrr and TTTTccccllll____GGGGeeeettttVVVVaaaarrrr2222 functions, and set from C extensions through the TTTTccccllll____SSSSeeeettttVVVVaaaarrrr and TTTTccccllll____SSSSeeeettttVVVVaaaarrrr2222 functions. They can also be unset via the TTTTccccllll____UUUUnnnnsssseeeettttVVVVaaaarrrr and TTTTccccllll____UUUUnnnnsssseeeettttVVVVaaaarrrr2222 functions. For complete information on these functions, please refer to the SSSSeeeettttVVVVaaaarrrr(3) manual page in the _d_o_c directory of the Berkeley Tcl distribution. LLLLIIIINNNNKKKKIIIINNNNGGGG TTTTCCCCLLLL VVVVAAAARRRRIIIIAAAABBBBLLLLEEEESSSS TTTTOOOO CCCC VVVVAAAARRRRIIIIAAAABBBBLLLLEEEESSSS TTTTccccllll____LLLLiiiinnnnkkkkVVVVaaaarrrr and TTTTccccllll____UUUUnnnnlllliiiinnnnkkkkVVVVaaaarrrr can be used to automatically keep Tcl variables synchronized with corresponding C variables. Once a Tcl variable has been linked to a C variable with TTTTccccllll____LLLLiiiinnnnkkkkVVVVaaaarrrr, anytime the Tcl variable is read the value of the C variable will be returned, and when the Tcl variable is written, the C variable will be updated with the new value. PPPPaaaaggggeeee 8888 CCCCoooommmmmmmmaaaannnndddd WWWWrrrriiiittttiiiinnnngggg((((3333TTTTccccllll)))) CCCCoooommmmmmmmaaaannnndddd WWWWrrrriiiittttiiiinnnngggg((((3333TTTTccccllll)))) TTTTccccllll____LLLLiiiinnnnkkkkVVVVaaaarrrr uses variable traces to keep the Tcl variable named by _v_a_r_N_a_m_e in sync with the C variable at the address given by _a_d_d_r. Whenever the Tcl variable is read the value of the C variable will be returned, and whenever the Tcl variable is written the C variable will be updated to have the same value. _I_n_t, _d_o_u_b_l_e, _b_o_o_l_e_a_n and _c_h_a_r * variables are supported. For more information, please examine the LLLLiiiinnnnkkkkVVVVaaaarrrr(3) manual page in the Berkeley Tcl distribution. AAAADDDDDDDDIIIINNNNGGGG NNNNEEEEWWWW MMMMAAAATTTTHHHH FFFFUUUUNNNNCCCCTTTTIIIIOOOONNNNSSSS TTTTOOOO TTTTCCCCLLLL As of Tcl version 7.0, math functions such as _s_i_n, _c_o_s, etc, are directly supported within Tcl expressions. These obsolete the Extended Tcl commands that provided explicit calls for these functions for many releases. New math functions can be added to Tcl, or existing math functions can be replaced, by calling TTTTccccllll____CCCCrrrreeeeaaaatttteeeeMMMMaaaatttthhhhFFFFuuuunnnncccc. For more information on adding math functions, please examine the CCCCrrrrttttMMMMaaaatttthhhhFFFFnnnncccc(3) manual page in the Berkeley Tcl distribution. PPPPEEEERRRRFFFFOOOORRRRMMMMIIIINNNNGGGG TTTTIIIILLLLDDDDEEEE SSSSUUUUBBBBSSSSTTTTIIIITTTTUUUUTTTTIIIIOOOONNNNSSSS OOOONNNN FFFFIIIILLLLEEEENNNNAAAAMMMMEEEESSSS The TTTTccccllll____TTTTiiiillllddddeeeeSSSSuuuubbbbsssstttt function is available to C extension writers to perform tilde substitutions on filenames. If the name starts with a ``~'' character, the function returns a new string where the name is replaced with the home directory of the given user. For more information please consult the TTTTiiiillllddddeeeeSSSSuuuubbbbsssstttt(3) manual page in the Berkeley Tcl distribution. SSSSEEEETTTTTTTTIIIINNNNGGGG TTTTHHHHEEEE RRRREEEECCCCUUUURRRRSSSSIIIIOOOONNNN LLLLIIIIMMMMIIIITTTT Tcl has a preset recursion limit that limits the maximum allowable nesting depth of calls within an interpreter. This is useful for detecting infinite recursions before other limits such as the process memory limit or, worse, available swap space on the system, are exceeded. The default limit is just a guess, however, and applications that make heavy use of recursion may need to call TTTTccccllll____SSSSeeeettttRRRReeeeccccuuuurrrrssssiiiioooonnnnLLLLiiiimmmmiiiitttt to raise this limit. For more information, please consult the SSSSeeeettttRRRReeeeccccLLLLmmmmtttt(3) manual page in the Berkeley Tcl distribution. HHHHAAAANNNNDDDDLLLLIIIINNNNGGGG SSSSIIIIGGGGNNNNAAAALLLLSSSS FFFFRRRROOOOMMMM TTTTCCCCLLLL EEEEXXXXTTTTEEEENNNNSSSSIIIIOOOONNNNSSSS If an event such as a signal occurs while a Tcl script is being executed, it isn't safe to do much in the signal handling routine -- the Tcl environment cannot be safely manipulated at this point because it could be in the middle of some operation, such as updating pointers, leaving the interpreter in an unreliable state. The only safe approach is to set a flag indicating that the event occurred, then handle the event later when the interpreter has returned to a safe state, such as after the current Tcl command completes. PPPPaaaaggggeeee 9999 CCCCoooommmmmmmmaaaannnndddd WWWWrrrriiiittttiiiinnnngggg((((3333TTTTccccllll)))) CCCCoooommmmmmmmaaaannnndddd WWWWrrrriiiittttiiiinnnngggg((((3333TTTTccccllll)))) The TTTTccccllll____AAAAssssyyyynnnnccccCCCCrrrreeeeaaaatttteeee, TTTTccccllll____AAAAssssyyyynnnnccccMMMMaaaarrrrkkkk, TTTTccccllll____AAAAssssyyyynnnnccccIIIInnnnvvvvooookkkkeeee, and TTTTccccllll____AAAAssssyyyynnnnccccDDDDeeeelllleeeetttteeee functions provide a safe mechanism for dealing with signals and other asynchronous events. For more information on how to use this capability, please refer to the AAAAssssyyyynnnncccc(3) manual page in the Berkeley Tcl distribution. PPPPAAAARRRRSSSSIIIINNNNGGGG BBBBAAAACCCCKKKKSSSSLLLLAAAASSSSHHHH SSSSEEEEQQQQUUUUEEEENNNNCCCCEEEESSSS The TTTTccccllll____BBBBaaaacccckkkkssssllllaaaasssshhhh function is called to parse Tcl backslash sequences. These backslash sequences are the usual sort that you see in the C programming language, such as \\\\nnnn for newline, \\\\rrrr for return, and so forth. TTTTccccllll____BBBBaaaacccckkkkssssllllaaaasssshhhh parses a single backslash sequence and returns a single character corresponding to the backslash sequence. For more info on this call, look at the BBBBaaaacccckkkkssssllllaaaasssshhhh(3) manual page in the Berkeley Tcl distribution. For information on the valid backslash sequences, consult the summary of Tcl language syntax, TTTTccccllll(n) in the same distribution. HHHHAAAASSSSHHHH TTTTAAAABBBBLLLLEEEESSSS _H_a_s_h _t_a_b_l_e_s provide Tcl with a high-performance facility for looking up and managing key-value pairs located and maintained in memory. Tcl uses hash tables internally to locate procedure definitions, Tcl variables, array elements, file handles and so forth. Tcl makes the hash table functions accessible to C extension writers as well. Hash tables grow automatically to maintain efficiency, rather than exposing the table size to the programmer at allocation time, which would needlessy add complexity to Tcl and would be prone to inefficiency due to the need to guess the number of items that will go into the table, and the seemingly inevitable growth in amount of data processed per run over the life of the program. For more information on hash tables, please consult the HHHHaaaasssshhhh(3) manual page in the Berkeley Tcl distribution. TTTTRRRRAAAACCCCIIIINNNNGGGG VVVVAAAARRRRIIIIAAAABBBBLLLLEEEE AAAACCCCCCCCEEEESSSSSSSSEEEESSSS The C extension writer can arrange to have a C routine called whenever a Tcl variable is read, written, or unset. Variable traces are the mechanism by which Tk toolkit widgets such as radio and checkbuttons, messages and so forth update without Tcl programmer intervention when their data variables are changed. They are also used by the routine that links Tcl and C variables, TTTTccccllll____LLLLiiiinnnnkkkkVVVVaaaarrrr, described above. TTTTccccllll____TTTTrrrraaaacccceeeeVVVVaaaarrrr is called to establish a variable trace. Entire arrays and individual array elements can be traced as well. If the programmer already has an array name in one string and a variable name in another, TTTTccccllll____TTTTrrrraaaacccceeeeVVVVaaaarrrr2222 can be called. Calls are also available to request information about traces and to delete them. PPPPaaaaggggeeee 11110000 CCCCoooommmmmmmmaaaannnndddd WWWWrrrriiiittttiiiinnnngggg((((3333TTTTccccllll)))) CCCCoooommmmmmmmaaaannnndddd WWWWrrrriiiittttiiiinnnngggg((((3333TTTTccccllll)))) For more information on variable traces, consult the TTTTrrrraaaacccceeeeVVVVaaaarrrr(3) manual page in the Berkeley Tcl distribution. TTTTRRRRAAAACCCCIIIINNNNGGGG EEEEXXXXEEEECCCCUUUUTTTTIIIIOOOONNNN Tcl has the ability to call C routines for every command it executes, up to a specified depth of nesting levels. The command TTTTccccllll____CCCCrrrreeeeaaaatttteeeeTTTTrrrraaaacccceeee creates an execution trace; TTTTccccllll____DDDDeeeelllleeeetttteeeeTTTTrrrraaaacccceeee deletes it. Command tracing is used in Extended Tcl to implement the _c_m_d_t_r_a_c_e Tcl command, a useful command for debugging Tcl applications. For complete information on execution tracing, please look at the CCCCrrrrttttTTTTrrrraaaacccceeee(3) manual pages in the Berkeley Tcl distribution. EEEEVVVVAAAALLLLUUUUAAAATTTTIIIINNNNGGGG TTTTCCCCLLLL EEEEXXXXPPPPRRRREEEESSSSSSSSIIIIOOOONNNNSSSS FFFFRRRROOOOMMMM CCCC TTTTccccllll____EEEExxxxpppprrrrLLLLoooonnnngggg, TTTTccccllll____EEEExxxxpppprrrrDDDDoooouuuubbbblllleeee, TTTTccccllll____EEEExxxxpppprrrrBBBBoooooooollll, and TTTTccccllll____EEEExxxxpppprrrrSSSSttttrrrriiiinnnngggg can be called to evaluate Tcl expressions from within a C routine. Depending on the routine called, the result is either a C _l_o_n_g, a _d_o_u_b_l_e, a boolean (_i_n_t with a value of 0000 or _1), or a _c_h_a_r * (pointed to by _i_n_t_e_r_p->_r_e_s_u_l_t). For complete information on evaluating Tcl expressions from C, you are invited to examine the EEEExxxxpppprrrrLLLLoooonnnngggg(3) manpage in the Berkeley Tcl distribution. PPPPAAAATTTTTTTTEEEERRRRNNNN MMMMAAAATTTTCCCCHHHHIIIINNNNGGGG The TTTTccccllll____SSSSttttrrrriiiinnnnggggMMMMaaaattttcccchhhh function can be called to see if a string matches a specified pattern. TTTTccccllll____SSSSttttrrrriiiinnnnggggMMMMaaaattttcccchhhh is called by the Tcl _s_t_r_i_n_g _m_a_t_c_h command, so the format for patterns is identical. The pattern format is similar to the one used by the C-shell; ssssttttrrrriiiinnnngggg(n) describes this format. More information about TTTTccccllll____SSSSttttrrrriiiinnnnggggMMMMaaaattttcccchhhh is available in the SSSSttttrrrrMMMMaaaattttcccchhhh(3) manpage in the Berkeley Tcl distribution. RRRREEEEGGGGUUUULLLLAAAARRRR EEEEXXXXPPPPRRRREEEESSSSSSSSIIIIOOOONNNN PPPPAAAATTTTTTTTEEEERRRRNNNN MMMMAAAATTTTCCCCHHHHIIIINNNNGGGG TTTTccccllll____RRRReeeeggggEEEExxxxppppMMMMaaaattttcccchhhh can be called to determine whether a string matches a regular expression. TTTTccccllll____RRRReeeeggggEEEExxxxppppMMMMaaaattttcccchhhh is used internally by the _r_e_g_e_x_p Tcl command. For more information on this function, please consult the RRRReeeeggggEEEExxxxpppp(3) manpage in the Berkeley Tcl distribution. MMMMAAAANNNNIIIIPPPPUUUULLLLAAAATTTTIIIINNNNGGGG TTTTCCCCLLLL LLLLIIIISSSSTTTTSSSS FFFFRRRROOOOMMMM CCCC EEEEXXXXTTTTEEEENNNNSSSSIIIIOOOONNNNSSSS The C extension writer often needs to create, manipulate and decompose Tcl lists. TTTTccccllll____SSSSpppplllliiiittttLLLLiiiisssstttt parses a list into an _a_r_g_v and _a_r_g_c like to the way command-line arguments are passed to a Tcl extension. TTTTccccllll____MMMMeeeerrrrggggeeee, likewise, creates a single string (pointer to a _c_h_a_r *) from an _a_r_g_v and _a_r_g_c. Two routines, TTTTccccllll____SSSSccccaaaannnnEEEElllleeeemmmmeeeennnntttt and TTTTccccllll____CCCCoooonnnnvvvveeeerrrrttttEEEElllleeeemmmmeeeennnntttt, do most of the work of TTTTccccllll____MMMMeeeerrrrggggeeee, and may also be of use to the C programmer. PPPPaaaaggggeeee 11111111 CCCCoooommmmmmmmaaaannnndddd WWWWrrrriiiittttiiiinnnngggg((((3333TTTTccccllll)))) CCCCoooommmmmmmmaaaannnndddd WWWWrrrriiiittttiiiinnnngggg((((3333TTTTccccllll)))) For more information on these commands, please consult the SSSSpppplllliiiittttLLLLiiiisssstttt(3) manual page in the Berkeley Tcl distribution. CCCCOOOONNNNCCCCAAAATTTTEEEENNNNAAAATTTTIIIINNNNGGGG SSSSTTTTRRRRIIIINNNNGGGGSSSS TTTTccccllll____CCCCoooonnnnccccaaaatttt concatenates zero or more strings into a single string. The strings are space-separated. TTTTccccllll____CCCCoooonnnnccccaaaatttt works like _T_c_l__M_e_r_g_e, except that TTTTccccllll____CCCCoooonnnnccccaaaatttt does not attempt to make the resulting string into a valid Tcl list. TTTTccccllll____CCCCoooonnnnccccaaaatttt is documented in the CCCCoooonnnnccccaaaatttt(3) manpage in the Berkeley Tcl distribution. DDDDEEEETTTTEEEECCCCTTTTIIIINNNNGGGG WWWWHHHHEEEETTTTHHHHEEEERRRR OOOORRRR NNNNOOOOTTTT YYYYOOOOUUUU HHHHAAAAVVVVEEEE C routines that collect data to form a command to be passed to _T_c_l__E_v_a_l often need a way to tell whether they have a complete command already or whether they need more data. (Programs that read typed-in Tcl input such as Tcl shells need this capability.) TTTTccccllll____CCCCoooommmmmmmmaaaannnnddddCCCCoooommmmpppplllleeeetttteeee can be used to tell whether or not you have a complete command. For more information examine CCCCmmmmddddCCCCmmmmpppplllltttt(3) in the Berkeley Tcl distribution. RRRREEEECCCCOOOORRRRDDDDIIIINNNNGGGG CCCCOOOOMMMMMMMMAAAANNNNDDDDSSSS FFFFOOOORRRR CCCCOOOOMMMMMMMMAAAANNNNDDDD HHHHIIIISSSSTTTTOOOORRRRYYYY Tcl has a history mechanism that is accessed from Tcl through the _h_i_s_t_o_r_y command. To propagate commands into the command history, your extension should call _T_c_l__R_e_c_o_r_d_A_n_d_E_v_a_l. This command works just like _T_c_l__E_v_a_l, except that it records the command as well as executing it. _T_c_l__R_e_c_o_r_d_A_n_d_E_v_a_l should only be called with user-entered top-level commands, since the history mechanism exists to allow the user to easily access, edit and reissue previously issued commands. For complete information on this function, please examine the RRRReeeeccccoooorrrrddddEEEEvvvvaaaallll.3 manual page in the Berkeley Tcl distribution. CCCCOOOONNNNVVVVEEEERRRRTTTTIIIINNNNGGGG FFFFLLLLOOOOAAAATTTTIIIINNNNGGGG PPPPOOOOIIIINNNNTTTT VVVVAAAALLLLUUUUEEEESSSS TTTTOOOO SSSSTTTTRRRRIIIINNNNGGGGSSSS TTTTccccllll____PPPPrrrriiiinnnnttttDDDDoooouuuubbbblllleeee converts a C _d_o_u_b_l_e into an ASCII string. It ensures that the string output will continue to be interpreted as a floating point number, rather than an integer, by always putting a ``.'' or ``e'' into the string representing the number. The precision of the output string is controlled by the Tcl ttttccccllll____pppprrrreeeecccciiiissssiiiioooonnnn variable. For complete information on _T_c_l__P_r_i_n_t_D_o_u_b_l_e, examine PPPPrrrriiiinnnnttttDDDDbbbbllll(3) in the Berkeley Tcl distribution. CCCCRRRREEEEAAAATTTTIIIINNNNGGGG CCCCHHHHIIIILLLLDDDD PPPPRRRROOOOCCCCEEEESSSSSSSSEEEESSSS AAAANNNNDDDD PPPPIIIIPPPPEEEELLLLIIIINNNNEEEESSSS FFFFRRRROOOOMMMM TTTTccccllll____CCCCrrrreeeeaaaatttteeeePPPPiiiippppeeeelllliiiinnnneeee is a useful procedure for spawning child processes. The child (or pipeline of children) can have its standard input, output and error redirected from files, variables or pipes. To understand the meaning of the redirection symbols understood by this function, look at the eeeexxxxeeeecccc(n) Tcl command. For complete information on TTTTccccllll____CCCCrrrreeeeaaaatttteeeePPPPiiiippppeeeelllliiiinnnneeee, please examine CCCCrrrrttttPPPPiiiippppeeeelllliiiinnnn(3). PPPPaaaaggggeeee 11112222 CCCCoooommmmmmmmaaaannnndddd WWWWrrrriiiittttiiiinnnngggg((((3333TTTTccccllll)))) CCCCoooommmmmmmmaaaannnndddd WWWWrrrriiiittttiiiinnnngggg((((3333TTTTccccllll)))) AAAACCCCCCCCEEEESSSSSSSSIIIINNNNGGGG TTTTCCCCLLLL FFFFIIIILLLLEEEEHHHHAAAANNNNDDDDLLLLEEEESSSS FFFFRRRROOOOMMMM CCCC Files opened from your C code can be made visible to Tcl code via the TTTTccccllll____EEEEnnnntttteeeerrrrFFFFiiiilllleeee function. Likewise, Tcl filehandles passed to your C extension can be translated to a Posix _F_I_L_E * structure using the TTTTccccllll____GGGGeeeettttOOOOppppeeeennnnFFFFiiiilllleeee function. For complete explanations of these commands, please look at EEEEnnnntttteeeerrrrFFFFiiiilllleeee(3) in the Berkeley Tcl distribution. MMMMAAAANNNNAAAAGGGGIIIINNNNGGGG BBBBAAAACCCCKKKKGGGGRRRROOOOUUUUNNNNDDDD PPPPRRRROOOOCCCCEEEESSSSSSSS TTTTEEEERRRRMMMMIIIINNNNAAAATTTTIIIIOOOONNNN AAAANNNNDDDD CCCCLLLLEEEEAAAANNNNUUUUPPPP When a Posix system does a _f_o_r_k to create a new process, the process ID of the child is returned to the caller. After the child process exits, its process table entry (and some other data associated with the process) cannot be reclaimed by the operating system until a call to _w_a_i_t_p_i_d, or one of a couple of other, similar system calls, has been made by the parent process. The C extension writer who has created a subprocess, by whatever mechanism, can turn over responsibility for detecting the processes' termination and calling _w_a_i_t_p_i_d to obtain its exit status by calling TTTTccccllll____DDDDeeeettttaaaacccchhhhPPPPiiiiddddssss. TTTTccccllll____RRRReeeeaaaappppDDDDeeeettttaaaacccchhhheeeeddddPPPPrrrrooooccccssss is the C routine that will detect the termination of any processes turned over to Tcl, permitting the processes to be fully reclaimed by the operating system. For complete information on these routines, please look at _D_e_t_a_c_h_P_i_d_s(_3) in the Berkeley Tcl distribution. FFFFOOOORRRR MMMMOOOORRRREEEE IIIINNNNFFFFOOOORRRRMMMMAAAATTTTIIIIOOOONNNN In addition to the documentation referenced above, you can learn a lot by studying the source code of the commands added by Tcl, Tk and Extended Tcl. The _c_o_m_p._l_a_n_g._t_c_l Usenet newsgroup is read by tens of thousands of Tcl people, and is a good place to ask questions. Finally, if you have interactive Internet access, you can ftp to _f_t_p._a_u_d._a_l_c_a_t_e_l._c_o_m, the site for contributed Tcl sources. This site contains quite a few extensions, applications, and so forth, including several object-oriented extension packages. PPPPaaaaggggeeee 11113333